#include "bitmap_font.h"

#include "graphics/graphics.h"
#include "graphics/graphics_util.h"
#include "graphics/image.h"

#include "math/vec2.h"

#include "script/scripthelper.h"

#include "lang/lang.h"

#include "util/common_macros.h"		// macros
#include "util/log.h"		// macros
#include "util/mmgr.h"		// Needs to come in early

#include <cassert>
using namespace script;
using namespace LuaPlus;


static const int	MAX_GLYPHS = 512;

BitmapFont::BitmapFont( const std::string& Name ) :
	Font(Name),
	m_pTexture(0),
	m_FontC(0)
{

}

BitmapFont::~BitmapFont()
{
	int	Test = 0;
	UTIL_SAFE_DELETE(m_pTexture);
}

bool	BitmapFont::Load(const std::string& File)
{
	LuaPlus::LuaState*	pScript = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoFile(*pScript, File))
	{
		_LOG(MSG_ERROR, "Unable to load font file " << File << "!");
		 LuaState::Destroy( pScript );
		return false;
	} else
	{
		LuaPlus::LuaObject tempObj = pScript->GetGlobal("Offset");
		
		m_LineSpacing = ScriptHelper::GetInt(tempObj);
		tempObj       = pScript->GetGlobal("Img");
		m_TextureFile = ScriptHelper::GetString(tempObj);
		if (!m_TextureFile.empty())
		{
			m_pTexture = GetGraphics()->LoadImageFromFile(m_TextureFile);
		}
		if (!m_pTexture) return false;

		m_TexWidth = m_pTexture->GetWidth();
		m_TexHeight = m_pTexture->GetHeight();
		LuaPlus::LuaObject	Glyph = ScriptHelper::GetObj(*pScript, "Font");
		if (Glyph.IsTable())
		{
			for (int i=0; i<Glyph.GetTableCount(); i++)
			{
				LuaPlus::LuaObject	GlyphTable = Glyph.GetByIndex(i+1);
				if (GlyphTable.IsTable())
				{
					GlyphData* pGlyph = new GlyphData;
					pGlyph->xp = ScriptHelper::GetTableInt(GlyphTable, "x", 0);
					pGlyph->yp = ScriptHelper::GetTableInt(GlyphTable, "y", 0);
					pGlyph->Width = ScriptHelper::GetTableInt(GlyphTable, "w", 0);
					pGlyph->Height = ScriptHelper::GetTableInt(GlyphTable, "h", 0);
					pGlyph->OffsetX = ScriptHelper::GetTableInt(GlyphTable, "Offset", 0);
					pGlyph->PreOffset = ScriptHelper::GetTableInt(GlyphTable, "PreOffset", 0);
					std::string	Name = ScriptHelper::GetTableString(GlyphTable, "Glyph", "");

					m_Height = ( i ? UTIL_HIGH((int)m_Height, pGlyph->Height) : pGlyph->Height);
//					m_LineSpacing = 1;

					if (!Name.empty())		// legacy string
					{
						pGlyph->Glyph = (unsigned short)Name[0];
					} else					// uses unicode
					{
						pGlyph->Glyph = ScriptHelper::GetTableInt(GlyphTable, "GlyphID", 0);
					}
					if (pGlyph->Glyph=='\'')
					{
						int Foo = 0;
					}
					if (pGlyph->Glyph!=0)
					{
						pGlyph->TexX = ScriptHelper::GetTableInt(GlyphTable, "u1", 0);
						pGlyph->TexY = ScriptHelper::GetTableInt(GlyphTable, "v1", 0);
						pGlyph->TexW = ScriptHelper::GetTableInt(GlyphTable, "u2", 0) - pGlyph->TexX;
						pGlyph->TexH = ScriptHelper::GetTableInt(GlyphTable, "v2", 0) - pGlyph->TexY;
						pGlyph->Pos.x = float(pGlyph->xp) / float(m_TexWidth);
						pGlyph->Pos.y = float(pGlyph->yp) / float(m_TexHeight);
						pGlyph->TimeStamp = 0;
						pGlyph->ToCache = false;

						pGlyph->Size.x = float(pGlyph->Width) / float(m_TexWidth);
						pGlyph->Size.y = float(pGlyph->Height) / float(m_TexHeight);

						unsigned int Key = pGlyph->Glyph;
						m_GlyphMap.AddElement(pGlyph->Glyph, pGlyph);
					} else
					{							 
						delete pGlyph;
					}
				}
			}
		} 

	}
	// IMPORTANT: CANNOT DESTROY BEFORE WE'RE OUT OF THAT IF STATEMENT!
	LuaState::Destroy( pScript );
	return true;
}


bool	BitmapFont::Init(	 const std::string& _Face,
                unsigned long      _Width,
                unsigned long      _Height,
				bool				_Italic,
				unsigned int		_Weight)
{
	return Load(_Face);
}

void	BitmapFont::Resize(const std::string& _Face, int Width, int Height, int Weight, unsigned long CharSet)
{

}


void	BitmapFont::Render(	const std::wstring& Text,
							const math::Vec2& Pos,
							const math::Vec2& Size ,
							unsigned int Flags, 
							COLOR		Color ,
							bool	Clip)
{
	if (Size.x <= 0.00001f) return ;	// gonna cause a crash!
	GlyphData*			GlyphA[MAX_CHAR];
	LineData			LineA[MAX_LINES];
	int					LineC=0, GlyphC=0;
	if (Text.empty()) return;
	assert(Text.size() < MAX_CHAR);

	Graphics*			pGraph = GetGraphics();
	int					ScreenW = pGraph->GetScreenWidth();
	int					ScreenH = pGraph->GetScreenHeight();


	// draw the text
	BuildGlyphData(Text,int( Size.x * ScreenW), int(Size.y* ScreenH), LineA, GlyphA, LineC, GlyphC, true);
	RenderGlyphData(Pos, Size, Color, LineA, GlyphA, LineC, GlyphC, Flags, true);

}


void	BitmapFont::SetTexture()
{
	if (m_pTexture) m_pTexture->SetTextureStage(0);
}



float	BitmapFont::GetHeight()
{
	return Font::GetHeight();
	//return 0.0f;
}

void	BitmapFont::Flush()
{

}

void	BitmapFont::Recreate()
{

}

bool	BitmapFont::CustomInit()
{
	return true;
}
